from django_redis import get_redis_connection
from rest_framework import serializers

from .models import OAuthQQUser
from .utils import check_save_user_token
from apps.users.models import User


class QQauthSerializer(serializers.Serializer):
    """open_id绑定用户序列化器"""
    access_token = serializers.CharField(label='操作凭证')
    mobile = serializers.RegexField(label='手机号', regex=r'^1[3-9]\d{9}$')  # 表示定义正则格式，值必须要定义匹配正则才能通过反序列化器
    password = serializers.CharField(label='密码', max_length=20, min_length=8)
    sms_code = serializers.CharField(label='短信验证码')

    def validate(self, attrs):
        # 1、把加密的open_id取出来解密
        access_token = attrs.pop("access_token")
        open_id = check_save_user_token(access_token)
        if open_id is None:
            raise serializers.ValidationError("OpenId无效")
        # 2、把解密后的open_id添加至attrs(以备后期create方法中绑定使用)
        attrs["open_id"] = open_id
        # 3、校验验证码
        redis_conn = get_redis_connection('verify_codes')
        mobile = attrs['mobile']
        real_sms_code = redis_conn.get('sms_%s' % mobile)
        # 向redis存储数据时都是以字条串进行存储的,取出来后都是bytes类型 [bytes]
        if real_sms_code is None or attrs['sms_code'] != real_sms_code.decode():
            raise serializers.ValidationError('验证码错误')

        # 4、获取手机号查询user表是否已注册，如已注册则判断密码是否匹配
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            if user.check_password(attrs["password"] is False):
                raise serializers.ValidationError("密码错误")
            else:
                attrs["user"] = user  # 如果用户存在密码正确，把当前user存储到反序列化大字典以备后期绑定
        return attrs

    def create(self, validated_data):
        """如果存在user则直接关联保存QQmodel否则需要先在user中添加user之后在关联QQ模型"""
        user = validated_data["user"]
        if user is None:
            user = User(username=validated_data.get('mobile'),
                        mobile=validated_data.get('mobile'))
            user.set_password(validated_data.get('password'))
            user.save()
        OAuthQQUser.objects.create(
            user_id=user,
            open_id=validated_data.get("open_id")
        )
        return user
